package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.huiminpay.agent.api.PayChannelAgentService;
import com.huiminpay.agent.conf.AliConfigParam;
import com.huiminpay.agent.dto.AlipayBean;
import com.huiminpay.agent.dto.PaymentResponseDTO;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.util.AmountUtil;
import com.huiminpay.common.cache.util.EncryptUtil;
import com.huiminpay.common.cache.util.PaymentUtil;
import com.huiminpay.merchant.api.AppService;
import com.huiminpay.merchant.api.IMerchantService;
import com.huiminpay.transaction.api.dto.OrderResultDTO;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PayOrderDTO;
import com.huiminpay.transaction.api.dto.QRCodeDto;
import com.huiminpay.transaction.api.service.PayChannelService;
import com.huiminpay.transaction.api.service.TransactionService;
import com.huiminpay.transaction.convert.PayOrderConvert;
import com.huiminpay.transaction.entity.PayOrder;
import com.huiminpay.transaction.mapper.PayOrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

@Slf4j
@Service
public class TransactionServiceImpl implements TransactionService {

    @Value("${huiminpay.payurl}")
    private String payUrl;
    @Reference
    IMerchantService merchantService;
    @Reference
    AppService appService;

    @Resource
    PayOrderMapper payOrderMapper;

    @Reference
    PayChannelService payChannelService;
    @Reference
    PayChannelAgentService payChannelAgentService;

    /**
     * \* 生成门店二维码
     * \* @param qrCodeDto，传入merchantId,appId、storeid、channel、subject、body
     * \* @return 支付入口URL，将二维码的参数组成json并用base64编码
     * \* @throws BusinessException
     * @param qrCodeDto
     */
    @Override
    public String createStoreQRCode(QRCodeDto qrCodeDto) throws BusinessException {
        // 校验应用和门店
        verifyAppAndStore(qrCodeDto.getMerchantId(),qrCodeDto.getAppId(),qrCodeDto.getStoreId());

        //1. 生成支付信息
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setMerchantId(qrCodeDto.getMerchantId());
        payOrderDTO.setAppId(qrCodeDto.getAppId());
        payOrderDTO.setStoreId(qrCodeDto.getStoreId());
        payOrderDTO.setSubject(qrCodeDto.getSubject());//显示订单标题
        payOrderDTO.setChannel("huimin_c2b");//服务类型
        payOrderDTO.setBody(qrCodeDto.getBody());//订单内容
        String jsonString = JSON.toJSONString(payOrderDTO);
        log.info("transaction service createStoreQRCode,JsonString is {}",jsonString);

        // 将支付信息保存到票据中
        String ticket = EncryptUtil.encodeUTF8StringBase64(jsonString);
        //支付入口
        String payEntryUrl = payUrl +ticket;
        log.info("transaction service createStoreQRCode,pay‐entry is {}",payEntryUrl);
        return payEntryUrl;
    }

    /**
     * 校验应用和门店是否属于当前登录商户
     * @param merchantId
     * @param appId
     * @param storeId
     */
    private void verifyAppAndStore(Long merchantId,String appId,Long storeId) {
        //判断应用是否属于当前商户
        Boolean contains = appService.queryAppInMerchant(appId, merchantId);
        if (!contains) {
            throw new BusinessException(CommonErrorCode.E_200005);
        }
        //判断门店是否属于当前商户
        Boolean containsStore = merchantService.queryStoreInMerchant(storeId, merchantId);
        if (!containsStore) {
            throw new BusinessException(CommonErrorCode.E_200006);
        }
    }
    /**
     * 支付宝订单保存
     * @param payOrderDTO
     * @return
     */
    public PaymentResponseDTO submitOrderByAli(PayOrderDTO payOrderDTO) throws BusinessException{
        //保存订单
        payOrderDTO.setPayChannel("ALIPAY_WAP");
        //保存订单到聚合支付平台数据库
        PayOrderDTO order = save(payOrderDTO);
        //调用支付代理服务请求第三方支付系统
        //调用支付渠道代理服务支付宝下单接口
        System.out.println(order.getTradeNo());
        PaymentResponseDTO paymentResponseDTO = alipayH5(order.getTradeNo());
        return paymentResponseDTO;
    }

    /**
     * \* 更新订单支付状态
     * \* @param tradeNo  惠民平台订单号
     * \* @param payChannelTradeNo 支付宝或微信的交易流水号
     * \* @param state  订单状态 交易状态支付状态,0‐订单生成,1‐支付中(目前未使用),2‐支付成功,4‐关闭 5‐‐失败
     * @param tradeNo
     * @param payChannelTradeNo
     * @param state
     */
    @Override
    public void updateOrderTradeNoAndTradeState(String tradeNo, String payChannelTradeNo, String state) {
        LambdaUpdateWrapper<PayOrder> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(PayOrder::getTradeNo,tradeNo)
                .set(PayOrder::getPayChannelTradeNo,payChannelTradeNo)
                .set(PayOrder::getTradeState,state);
        if (state!=null &&"2".equals(state)) {
            wrapper.set(PayOrder::getPaySuccessTime, LocalDateTime.now());
        }
        payOrderMapper.update(null, wrapper);
    }

    private PaymentResponseDTO alipayH5(String tradeNo) {
        //构建支付实体
        AlipayBean alipayBean = new AlipayBean();

        //根据订单号查询订单详情
        OrderResultDTO payOrderDTO = queryPayOrder(tradeNo);
        alipayBean.setOutTradeNo(tradeNo);
        alipayBean.setSubject(payOrderDTO.getSubject());
        String totalAmount = null;//支付宝那边入参是元
        try {
            //将分转成元
            totalAmount = AmountUtil.changeF2Y(payOrderDTO.getTotalAmount().toString());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(CommonErrorCode.E_300006);
        }
        alipayBean.setTotalAmount(totalAmount);
        alipayBean.setBody(payOrderDTO.getBody());
        alipayBean.setStoreId(payOrderDTO.getStoreId());
        alipayBean.setExpireTime("30m");

        //根据应用、服务类型、支付渠道查询支付渠道参数
        PayChannelParamDTO payChannelParamDTO =
                payChannelService.queryParamByAppPlatformAndPayChannel(payOrderDTO.getAppId(),
                        payOrderDTO.getChannel(), "ALIPAY_WAP");
        System.out.println(payChannelParamDTO);
        if(payChannelParamDTO == null){
            throw new BusinessException(CommonErrorCode.E_300007);
        }
        //支付宝渠道参数
        AliConfigParam aliConfigParam = JSON.parseObject(payChannelParamDTO.getParam(),
                AliConfigParam.class);
        //字符编码
        aliConfigParam.setCharest("utf-8");
        PaymentResponseDTO payOrderResponse = payChannelAgentService
                .createPayOrderByAliWAP(aliConfigParam, alipayBean);
        log.info("支付宝H5支付响应Content:" + payOrderResponse.getContent());
        return payOrderResponse;
    }

    private OrderResultDTO queryPayOrder(String tradeNo) {
        PayOrder payOrder = payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTradeNo, tradeNo));
        return PayOrderConvert.INSTANCE.entity2dto(payOrder);
    }



    private PayOrderDTO save(PayOrderDTO payOrderDTO)throws BusinessException {
        PayOrder payOrder = PayOrderConvert.INSTANCE.dto2entity(payOrderDTO);
        //订单号
        payOrder.setTradeNo(PaymentUtil.genUniquePayOrderNo());//采用雪花片算法
        //订单创建时间
        payOrder.setCreateTime(LocalDateTime.now());
        //过期时间是30分钟后
        payOrder.setExpireTime(LocalDateTime.now().plus(30, ChronoUnit.MINUTES));
        //支付币种  人民币
        payOrder.setCurrency("CNY");
        payOrder.setTradeState("0");//订单状态，0：订单生成
        payOrderMapper.insert(payOrder);//插入订单
        return PayOrderConvert.INSTANCE.entityTiDto(payOrder);
    }

}
